/*
 * Salida.cpp
 *
 *  Created on: 02/10/2012
 */

#include "Salida.h"

Salida::Salida(int numeroEstacionamiento, int numeroSalida):
	numeroSalida (numeroSalida),
	numeroEstacionamiento (numeroEstacionamiento),
	salidaAbierta (true),
	colaSalida (Cola<MensajeTicket>((char*)ARCHIVO_COLAS_SALIDAS, numeroEstacionamiento)),
	colaEstacionamiento (Cola<MensajeTicket>((char*)ARCHIVO_COLAS_ESTACIONAMIENTOS, numeroEstacionamiento)) {

	SignalHandler::getInstance()->registrarHandler(SIGUSR1, this);
	SignalHandler::getInstance()->registrarHandler(SIGINT, this);
	SignalHandler::getInstance()->registrarHandler(SIGTERM, this);

	Log::getInstance()->loguear("Salida " + intToString(this->numeroEstacionamiento) + "." +
		intToString(this->numeroSalida) + ": creada.");
}

Salida::~Salida() {
	SignalHandler::getInstance()->removerHandler(SIGUSR1);
	SignalHandler::getInstance()->removerHandler(SIGINT);
	SignalHandler::getInstance()->removerHandler(SIGTERM);
	SignalHandler::destruir();

	Log::getInstance()->loguear("Salida " + intToString(this->numeroEstacionamiento) + "." +
		intToString(this->numeroSalida) + ": destruida.");
}

/**
 * Handler de señales:
 * SIGUSR1: Señal que envia el estacionamiento para finalizar la simulación.
 */
int Salida::handleSignal(int signum){
	if (signum == SIGUSR1){
		Log::getInstance()->loguear("Salida " + intToString(this->numeroEstacionamiento) + "." +
			intToString(this->numeroSalida) + ": me llego SIGUSR1. Voy a finalizar.");
		this->salidaAbierta = false;

	} else if (signum == SIGINT){
		Log::getInstance()->loguear("Salida " + intToString(this->numeroEstacionamiento) + "." +
			intToString(this->numeroSalida) + ": me llego SIGINT. No hago nada.");
		// La señal la toma el terminador para detener la ejecución.

	} else if (signum == SIGTERM){
		Log::getInstance()->loguear("Salida " + intToString(this->numeroEstacionamiento) + "." +
			intToString(this->numeroSalida) + ": me llego SIGTERM. No hago nada.");
		// La señal la toma el terminador para detener la ejecución.

	}
	return 0;
}

/**
 * Lee la cola de mensajes de las salidas esperando por un auto que quiera salir.
 */
void Salida::sacarAutos(){
	MensajeTicket mensaje;
	while(this->salidaAbierta){
		int resultado = this->colaSalida.leer(this->numeroSalida + 1, &mensaje); // El +1 es para que el mtype no sea cero.
		if (resultado != -1){
			this->liberarLugar(mensaje.ticket);
		}
	}
	Log::getInstance()->imprimir("Salida " + intToString(this->numeroEstacionamiento) + "." +
			intToString(this->numeroSalida) + ": Se cierra la salida.");
}

/**
 * Le envia un mensaje al estacionamiento informandole el lugar que se deja desocupado.
 */
void Salida::liberarLugar(Ticket ticket){
	Log::getInstance()->imprimir("Salida " + intToString(this->numeroEstacionamiento) + "." +
		intToString(this->numeroSalida) + ": Se libera el lugar " + intToString(ticket.getLugarOcupado()) + ".");

	MensajeTicket mensaje;
	mensaje.mtype = SALIDA_LIBERA_LUGAR;
	mensaje.ticket = ticket;
	this->colaEstacionamiento.escribir(mensaje);
}

